package adventure.commands;

import adventure.*;
import adventure.misc.Currency;
import adventure.placeable.Item;
import adventure.placeable.Mobile;
import colour.ColourUtil;
import player.*;

/**
 *
 * @author Michael Hanns
 *
 */
public class Purchase extends AbstractCommand {

    Currency currency;

    public Purchase(Adventure a) {
        super(a, new String[]{"PURCHASE", "BUY"});
        this.currency = a.getCurrency();
    }

    @Override
    public String validateAndExecute(Player p, String[] args) {
        if (((AdventureEdit) adv).getRoomManager().isLightPresent(p.x(), p.y(), p.z())) {
            if (args.length == 1) {
                return listItems(p);
            } else if (((AdventureEdit) adv).getRoomManager().isLightPresent(p.x(), p.y(), p.z())) {
                int fromPosition = 0;
                for (int x = 0; x < args.length; x++) {
                    if (args[x].equalsIgnoreCase("from")) {
                        fromPosition = x;
                    }
                }

                if (args.length > 1 && fromPosition > 1) {
                    String item = args[1];
                    for (int x = 2; x < fromPosition; x++) {
                        item = item.concat(" ".concat(args[x]));
                    }

                    if (fromPosition < args.length - 1) {
                        String target = args[fromPosition + 1];

                        for (int x = fromPosition + 2; x < args.length; x++) {
                            target = target.concat(" ".concat(args[x]));
                        }
                        return purchase(p, item, target);
                    } else {
                        return "Purchase " + item + " from whom?\nSyntax: purchase <item> [from <mobile>]";
                    }
                } else {
                    String item = args[1];
                    for (int x = 2; x < args.length; x++) {
                        item = item.concat(" ".concat(args[x]));
                    }

                    return purchase(p, item);
                }
            }
            return "Purchase what from whom?\nSyntax: purchase <item> [from <mobile>]";
        } else {
            return "You cannot see anything in the darkness!";
        }
    }

    private String listItems(Player player) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        Mobile[] vendors = rooms.getRoomVendors(x, y, z);

        String output = "";

        Item item;
        int n;
        for (int c = 0; c < vendors.length; c++) {
            n = 0;

            output += ColourUtil.colourise(vendors[c].getAliveName(), ColourUtil.mobile) + " has the following for sale:\n";
            output += ColourUtil.colourise("---\n", ColourUtil.yellow);

            if (vendors[c].getInventoryItem(0).getID() != 0) {

                int maxLength = 0;
                int maxTypeLength = 0;
                int usesLength;
                int maxUsesLength = 0;

                while ((item = vendors[c].getInventoryItem(n++)).getID() != 0) {
                    if (item.getName().length() > maxLength) {
                        maxLength = item.getName().length();
                    }

                    if (item.getItemType().length() > maxTypeLength) {
                        maxTypeLength = item.getItemType().length();
                    }

                    if (item.isConsumable()) {
                        usesLength = String.valueOf(item.getUsesLeft()).length()
                                + String.valueOf(item.getTotalUses()).length() + 10;
                        if (usesLength > maxUsesLength) {
                            maxUsesLength = usesLength;
                        }
                    }
                }
                n = 0;

                while ((item = vendors[c].getInventoryItem(n++)).getID() != 0) {
                    String namePlusWhiteSpace = item.getName();
                    while (namePlusWhiteSpace.length() < maxLength) {
                        namePlusWhiteSpace += " ";
                    }
                    namePlusWhiteSpace = ColourUtil.colourise(namePlusWhiteSpace, ColourUtil.item);

                    String itemTypePlusWhiteSpace = item.getItemType();
                    while (itemTypePlusWhiteSpace.length() < maxTypeLength) {
                        itemTypePlusWhiteSpace += " ";
                    }

                    String itemUsesPlusWhiteSpace;
                    if(item.isConsumable()) {
                        itemUsesPlusWhiteSpace = " (uses: "
                            + item.getUsesLeft() + "/" + item.getTotalUses() + ")";
                    } else {
                        itemUsesPlusWhiteSpace = "";
                    }
                    while (itemUsesPlusWhiteSpace.length() < maxUsesLength) {
                        itemUsesPlusWhiteSpace += " ";
                    }

                    int price = getPurchase(item, vendors[c].getVendorModifier());
                    String currencyCost;
                    if (price > 1) {
                        currencyCost = ColourUtil.colourise(price + " " + currency.getPlural(), ColourUtil.currency);
                    } else {
                        currencyCost = ColourUtil.colourise(price + " " + currency.getSingular(), ColourUtil.currency);
                    }

                    output += namePlusWhiteSpace
                            + " : " + itemTypePlusWhiteSpace
                            + itemUsesPlusWhiteSpace
                            + " - " + currencyCost + "\n";
                }
            } else {
                output += "nothing\n";
            }

            if (c != vendors.length - 1) {
                output += "\n";
            }
        }

        if (output.length() == 0) {
            output = "There are no vendors here to purchase from!";
        }


        return output;
    }

    private String purchase(Player player, String targetItem, String targetVendor) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        Mobile[] vendors = rooms.getRoomVendors(x, y, z);
        Item item;

        String vendorName = "";


        for (int c = 0; c < vendors.length; c++) {
            if (vendors[c].getName().toUpperCase().startsWith(targetVendor.toUpperCase())) {
                for (int d = 0; (item = vendors[c].getInventoryItem(d)).getID() != 0; d++) {
                    if (item.getName().toUpperCase().startsWith(targetItem.toUpperCase())) {
                        return itemTransaction(player, item, vendors[c]);
                    }
                }
                vendorName = vendors[c].getAliveName();
            }
        }

        if (vendorName.length() > 0) {
            return ColourUtil.colourise(
                    vendorName.toUpperCase().substring(0, 1)
                    + vendorName.substring(1), ColourUtil.mobile)
                    + " does not have any " + targetItem + " to sell you!";
        }

        return "You don't see any " + targetVendor + " that will sell you " + targetItem + "!";
    }

    private String purchase(Player player, String targetItem) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        Mobile[] vendors = rooms.getRoomVendors(x, y, z);
        Item item;

        for (int c = 0; c < vendors.length; c++) {
            for (int d = 0; (item = vendors[c].getInventoryItem(d)).getID() != 0; d++) {
                if (item.getName().toUpperCase().startsWith(targetItem.toUpperCase())) {
                    return itemTransaction(player, item, vendors[c]);
                }
            }
        }

        if (vendors.length > 0) {
            String vendorNames = "";
            if (vendors.length > 1) {
                for (int c = 0; c < vendors.length - 1; c++) {
                    vendorNames += ColourUtil.colourise(
                            vendors[0].getName().toUpperCase().substring(0, 1)
                            + vendors[0].getName().substring(1), ColourUtil.mobile);
                    if (c != vendors.length - 2) {
                        vendorNames += ", ";
                    }
                }
                vendorNames += " or " + ColourUtil.colourise(
                        vendors[vendors.length - 1].getName().toUpperCase().substring(0, 1)
                        + vendors[vendors.length - 1].getName().substring(1), ColourUtil.mobile);

                return vendorNames
                        + " do not have any " + targetItem + " to sell you!";
            } else {
                vendorNames = vendors[0].getName().toUpperCase().substring(0, 1)
                        + vendors[0].getName().substring(1);
                return ColourUtil.colourise(
                        vendorNames, ColourUtil.mobile)
                        + " does not have any " + targetItem + " to sell you!";

            }
        }

        return "You don't see anyone to sell you " + targetItem + "!";
    }

    private String itemTransaction(Player player, Item item, Mobile vendor) {
        int itemPrice = getPurchase(item, vendor.getVendorModifier());

        if (player.getCurrencyAmount() >= itemPrice) {
            player.takeCurrency(itemPrice);
            vendor.addCurrencyAmount(itemPrice);
            player.giveItem(vendor.takeInventoryItem(item));

            String priceOut;
            if (itemPrice == 1) {
                priceOut = "a " + currency.getSingular();
            } else {
                priceOut = itemPrice + " " + currency.getPlural();
            }

            out.broadcastLocalToPlayer(player,
                    ColourUtil.colourise(player.getAliveName(), ColourUtil.player)
                    + " purchases " + ColourUtil.colourise(item.getName(), ColourUtil.item)
                    + " from " + ColourUtil.colourise(vendor.getName(), ColourUtil.mobile)
                    + " for " + ColourUtil.colourise(priceOut, ColourUtil.currency)
                    + ".");

            return "You purchase " + ColourUtil.colourise(item.getName(), ColourUtil.item)
                    + " from " + ColourUtil.colourise(vendor.getName(), ColourUtil.mobile)
                    + " for " + ColourUtil.colourise(priceOut, ColourUtil.currency)
                    + ".";
        }


        return "You do not have enough " + currency.getPlural() + " to pay for "
                + ColourUtil.colourise(item.getName(), ColourUtil.item) + "!";
    }

    private int getPurchase(Item item, double vendorMod) {
        double baseValue = item.getCurrencyValue();

        if (item.isConsumable()) {
            baseValue = baseValue * ((double) item.getUsesLeft() / (double) item.getTotalUses());
        }

        return (int) (baseValue + (baseValue * vendorMod / 100));
    }
}
